#include "mysqlconnectionpool.h"
#include <algorithm>
#include <condition_variable>
#include <cppconn/connection.h>
#include <exception>
#include <memory>
#include <mutex>
#include <mysql_driver.h>
#include "../util/logger.h"
namespace Yizhi{
    MysqlConnectionPool::MysqlConnectionPool(const std::string &url,const std::string& username,std::string& psw
        ,const std::string schema,size_t size)
        :m_url(url)
        ,m_username(username)
        ,m_pass(psw)
        ,m_poolsize(size)
        ,m_schema(schema){
           try{
             for(auto i=0;i<m_poolsize;i++){
                sql::mysql::MySQL_Driver *driver=sql::mysql::get_mysql_driver_instance();
                std::unique_ptr<sql::Connection>con(driver->connect(m_url,m_username,m_pass));
                con->setSchema(m_schema);
                m_connections.push(std::move(con));
            }
           }catch(std::exception &e){
             LOG_ERROR(e.what());
           }
        }



     std::unique_ptr<sql::Connection> MysqlConnectionPool ::GetConnection(){
        std::unique_lock<std::mutex> lock(m_mutex);

        m_cond.wait(lock,[this]{
           return m_stop||!m_connections.empty();
        });

        if(m_stop){
            return nullptr;
        }
        auto con=std::move(m_connections.front());
        m_connections.pop();
        return con;
     }

      void MysqlConnectionPool::ReturnConnection(std::unique_ptr<sql::Connection> con){
         if(con==nullptr){
            return;
         }
         std::lock_guard<std::mutex> lock(m_mutex);
         if(m_stop){
            return;
        }
        m_connections.push(std::move(con));
        m_cond.notify_one();
      }

     void MysqlConnectionPool::close(){
        std::lock_guard<std::mutex>lock(m_mutex);
        while(!m_connections.empty()){
            m_connections.pop();
        }
        m_stop=true;
        m_cond.notify_all();
     }
     

     MysqlConnectionPool::~MysqlConnectionPool(){
        close();
     }


}